<template>
  <basic-dialog :visible="show"
                :title="forCreate? '添加用户' : forEdit? '编辑用户' : ''"
                min-width="644px"
                @close="$emit('close')"
                :isFullScreen="false"
                :hasFooterMargin="false"
                :isShowInnerLoading="isSubmitting"
  >
    <!-- 正文 -->
    <q-form ref="form" class="dialog-content" greedy @submit="_submit">
      <div class="flex justify-between margin-t-20 margin-l-10 margin-r-10">
        <!-- 左侧 -->
        <div style="width: 50%; padding: 0 10px">
          <yz-input
            v-model.trim="user.number"
            title="员工编号"
            :maxlength="20"
            isRule
            :rules="forEdit ? [] : [0]"
          />
<!--                      :is-disable="forEdit"-->
          <div class="flex justify-between" style="align-items: baseline;">
            <!-- 姓名 -->
            <yz-input
              v-model.trim="user.name"
              title="姓名"
              style="width: calc(100% - 100px)"
              :maxlength="15"
              isRule
              :is-disable="forEdit"
              :rules="forEdit ? [] : [0]"
            />
            <!-- 性别 -->
            <q-option-group
              style="display: inline-flex;"
              v-model="user.genderCode"
              :options="genderOptions.filter(o => o.value !== 0)"
              inline
              dense
              color="primary"
            />
          </div>
          <!-- 手机号码 -->
          <yz-input
            v-model.trim="user.phone"
            title="手机号码"
            isRule
            :is-disable="forEdit"
            :rules="forEdit ? [] : [0]"
            :hint-rule="[val => /^(?:(?:\+|00)86)?1\d{10}$/.test(val) || '请输入正确手机号码']"
          />
          <!-- 邮箱 -->
          <yz-input
            v-model.trim="user.email"
            :maxlength="50"
            :rules="[12]"
            :is-rule="false"
            title="邮箱"
          />
          <!-- IC 卡号 -->
          <yz-input
            v-model.trim="user.icCardNumber"
            :maxlength="20"
            title="IC 卡号"
          />
          <!-- 所属部门 -->
          <select-tree
            label="所属部门"
            :tree-list="departmentsTree"
            :sel-tree="selectedDepartment"
            @treeChange="_onDepartmentSelected"
            node-key="id"
            is-require
          />
          <!-- 岗位 -->
          <q-select
            v-model="user.postCode"
            :options="postOptions"
            dense
            options-dense
            emit-value
            map-options
            outlined
            hint=""
          >
            <template v-slot:before>
              <label class="text-right name">
                <span>岗位:</span>
              </label>
            </template>
          </q-select>
          <!-- 角色 -->
          <q-select
            style="margin-bottom: 20px"
            class="select multipe-select"
            multiple
            outlined dense emit-value map-options options-dense
            :options="roleOptions"
            v-model="user.roleIds"
          >
            <q-tooltip v-if="user.roleIds">
              <span v-for="(item,index) in getRoleName(user.roleIds)" :key="index">
                <span v-if="!item">全部</span>
                {{item}}
              </span>
            </q-tooltip>
            <template v-slot:no-option>
              <div class="no-option"/>
            </template>
            <template v-slot:before>
              <label class="text-right name">
                <span>角色:</span>
              </label>
            </template>
          </q-select>
        </div>

        <!-- 右侧 -->
        <div style="width: 50%; padding: 0 10px">
          <!-- 照片 -->
          <div class="photo-box">
            <q-img
              class="photo"
              :src="user.photoUrl"
              spinner-color="white"
            >
              <div
                v-if="!user.photoUrl"
                style="height: 100%; width: 100%; background: #d0d6fb;"
              />
              <q-btn
                class="upload-btn"
                unelevated
                @click="_onUploadPhotoClick"
                :class="{ 'dashed-border': !user.photoUrl }"
              >
                <q-icon
                  v-if="!user.photoUrl"
                  size="96px"
                  name="iconfont icontubiao-61"
                  color="white"
                />
              </q-btn>
            </q-img>
            <input
              ref="fileInput"
              type="file"
              style="display: none;"
              accept="image/png, image/jpeg"
              @input="onPhotoFileSelected"
            />
          </div>
          <!-- 技能水平 -->
          <q-select
            v-model="user.skillLevelCode"
            :options="skillLevelOptions"
            dense
            options-dense
            emit-value
            map-options
            outlined
            hint=""
          >
            <template v-slot:before>
              <label class="text-right name">
                <span>技能水平:</span>
              </label>
            </template>
          </q-select>
          <div style="display: flex; justify-content: space-between;">

            <yz-input
              v-model.trim="user.price"
              :maxlength="20"
              :rules="[19]"
              style="width: 210px"
              :isRule="false"
              title="维修单价"
            ></yz-input>
            <div style="margin-top: 5px">元/小时</div>
            <q-icon name="iconfont icontubiao-72" class="font-16 cursor-pointer" style="margin-top: 7px">
              <q-tooltip>此字段在【维修工单】模块中，用于计算维修费用（人工单价)</q-tooltip>
            </q-icon>
          </div>
          <!-- 重置密码 -->
          <div style="text-align: center;">
            <q-btn
              v-if="false"
              label="重置密码"
              color="primary"
              unelevated
              @click="_onResetPwdClick"
            />
          </div>
        </div>
      </div>
      <!-- 底部按钮 -->
      <q-separator />
      <div class="dialog-footer text-center margin-t-10">
        <q-btn class="q-mr-md" outline color="primary" @click="$emit('close')" label="取消"/>
        <q-btn unelevated
               label="确认"
               color="primary"
               :loading="isSubmitting"
               type="submit" />
      </div>
    </q-form>
  </basic-dialog>
</template>

<script>
import SelectTree from 'src/components/select-tree'
import userManageApi from 'src/boot/system/user-manage'
import { mapGetters, mapMutations } from 'vuex'
import { removeToken, removeRefreshToken } from 'yz-help'
import { logout } from 'src/boot/login/login'
import { uploadFlie } from 'src/boot/template/template-upload'
import { goLoginPage } from '../../../permission'
import { isNil } from 'lodash'
export default {
  name: 'user-detail',
  components: {
    SelectTree
  },
  props: {
    /**
     * 用户详情对象
     * required
     */
    detail: {
      type: Object,
      required: true
    },

    /**
     * 该 dialog 用于编辑
     * {@link forView for-view}、{@link forCreate for-create}、{@link forEdit for-code-edit}
     * 三者必须有且仅有一项为 true
     * default: false
     */
    forEdit: {
      type: Boolean,
      default: false
    },

    /**
     * 该 dialog 用于创建
     * {@link forView for-view}、{@link forCreate for-create}、{@link forEdit for-code-edit}
     * 三者必须有且仅有一项为 true
     * default: false
     */
    forCreate: {
      type: Boolean,
      default: false
    },

    /**
     * 显示 dialog
     * default: false
     * required
     */
    show: {
      type: Boolean,
      default: false,
      required: true
    },

    /**
     * 树状结构的部门列表
     * default: []
     * required
     */
    departmentsTree: {
      type: Array,
      default: () => [],
      required: true
    },

    /**
     * 岗位 option 列表
     * default: []
     * required
     */
    postOptions: {
      type: Array,
      default: () => [],
      required: true
    },

    /**
     * 角色 option 列表
     * default: []
     * required
     */
    roleOptions: {
      type: Array,
      default: () => [],
      required: true
    },

    /**
     * 性别 option 列表
     * default: []
     * required
     */
    genderOptions: {
      type: Array,
      default: () => [],
      required: true
    },

    /**
     * 技能水平 option 列表
     * default: []
     * required
     */
    skillLevelOptions: {
      type: Array,
      default: () => [],
      required: true
    }
  },
  data () {
    return {
      // 用户详情对象
      // clone 自 props.detail
      user: {
        photoUrl: '',
        price: 0
      },

      // form 正在提交
      isSubmitting: false
    }
  },
  methods: {
    ...mapMutations(['SET_GUIDELINES', 'SET_TOKEN', 'SET_REFRESHTOKEN']),

    // 获取角色名称
    getRoleName (val) {
      let roleName = []
      val.forEach(val => {
        this.roleOptions.forEach(item => {
          if (val === item.value) {
            roleName.push(item.label)
          }
        })
      })
      return roleName
    },

    /**
     * 检查 props 中的值是否合法
     * 出现非法的 props 时抛出异常
     */
    _checkProps: function () {
      // forView、forEdit、forCreate 均为 false 或多于一项为 true
      let trueCount = [this.forEdit, this.forCreate].filter(o => o).length
      if (trueCount !== 1) {
        throw new Error('for-code-edit、for-create 必须有且只有一项为 true')
      }
    },

    /**
     * on 上传照片按钮被点击
     */
    _onUploadPhotoClick: function () {
      // 触发文件选择
      this.$refs.fileInput.dispatchEvent(new MouseEvent('click'))
    },

    // 选择照片
    onPhotoFileSelected () {
      if (!this.$utils.fileTypeHoldUp(this.$refs.fileInput.files[0].name, ['.jpg', '.jpeg', '.png'])) {
        this.$refs.fileInput.value = null
        return
      }
      // let photoOldUrl = this.user.photoUrl
      let file = this.$refs.fileInput.files
      let fileSize = file[0].size
      let fileMaxSize = 1024 * 1024 * 5
      if (fileSize <= fileMaxSize) {
        const path = this.CommonConfig.ossFilePath.avatarImagesDir
        // let res = await this.$uploadPublicFile(file, path)
        let res = this.$getUploadPath(file, path)
        // let newPhotoUrl = res.requestUrls[0].replace(/\?acl.+$/g, '')
        this.fileName = res.fileNameNew
        this.onSubscribe()
        uploadFlie(res.uploadPath, file[0], res.fileNameNew).then(res => {
          if (res.code !== '1200') {
            this.$showErrTips('上传失败，请稍后重试')
            this.closeUbscribeTopic()
          }
        }).catch(res => {
          console.log(res)
          this.closeUbscribeTopic()
        })
      } else {
        this.$message.warning('文件大小不能超过5M')
      }
      this.$refs.fileInput.value = null
    },
    onMessageArrived (message) {
      let msg = JSON.parse(message.body).data
      if (msg.requestId !== this.fileName) {
        return
      }
      if (msg.code + '' !== '200') {
        this.$showErrTips('上传失败，请稍后重试')
        this.closeUbscribeTopic()
        return
      }

      this.user.photoUrl = msg.data
      this.closeUbscribeTopic()
    },

    onSubscribe () {
      if (this.client) {
        this.client.subscribe(
          `${this.CommonConfig.socketConfig.SOCKET_TOPIC.uploadFile.subscribeTopic}${this.fileName}`, this.onMessageArrived, { id: `${this.fileName}` }
        )
      } else {
        setTimeout(() => {
          this.onSubscribe()
        }, 200)
      }
    },
    closeUbscribeTopic () {
      this.client.unsubscribe(`${this.fileName}`)
      this.$q.loading.hide()
    },

    /**
     * on 重置密码按钮被点击
     */
    _onResetPwdClick: function () {
      this.$q.dialog({
        title: `<p class="dialog-notice-title"><i class="iconfont icontubiao-28"></i>
          确定要重置密码吗？</p>`,
        message: '默认密码为 123456',
        html: true,
        ok: {
          unelevated: true,
          label: '确认'
        },
        cancel: {
          unelevated: true,
          outline: true,
          label: '取消'
        }
      })
        .onOk(() => {
          this._resetPwd()
        })
    },

    /**
     * 重置密码
     */
    _resetPwd: function () {
      userManageApi.resetPassword('123456', this.user.phone).then(res => {
        if (res.code === '1200') {
          this.$q.dialog({
            title: `<p class="dialog-notice-title"><i class="iconfont icontubiao-53"></i>
          保存成功`,
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          }).onOk(async () => {
            if (this.userInfo.user_name === this.user.phone) {
              await logout()
              removeToken()
              removeRefreshToken()
              this.SET_TOKEN('')
              this.SET_REFRESHTOKEN('')
              goLoginPage()
              // this.$router.push('/login')
            }
          })
        }
      })
    },

    /**
     * 提交表单
     */
    _submit: function () {
      // this.$refs.form.validate().then(success => {
      //   if (success) {
      this.isSubmitting = true
      let promise
      if (this.forCreate) {
        promise = userManageApi.createUser(this.user)
      }
      if (this.forEdit) {
        promise = userManageApi.editUser(this.user.id, this.user)
      }

      promise.then(resp => {
        if (resp.success) {
          this.$emit('submitted')
          if (this.forCreate) {
            this.$message.success('新增成功')
          } else if (this.forEdit) {
            this.$message.success('编辑成功')
          }
        } else {
          this.$message.error(resp.message)
        }
      }).finally(() => {
        this.isSubmitting = false
      })
      //   }
      // })
    },

    /**
     * on 修改 department
     * @param department
     */
    _onDepartmentSelected: function (department) {
      this.user.departmentId = department.id
    },

    /**
     * 重新组织 props.detail 的结构，并 clone 到 data.user
     */
    _cloneDetailToUser: function () {
      let o = this.detail
      if (o) {
        this.user = Object.assign({}, o, {
          departmentId: o.department ? o.department.id : undefined,
          roleIds: o.roles ? o.roles.map(role => role.id) : undefined,
          genderCode: o.genderCode === undefined ? 1 : o.genderCode,
          photoUrl: o.photoUrl === undefined ? '' : o.photoUrl,
          price: isNil(o.price) ? '' : o.price,
          email: o.email === '--' ? '' : o.email
        })
      }

      delete this.user.department
      delete this.user.roles
    }
  },
  computed: {
    ...mapGetters(['userInfo', 'client']),
    // 已关联微信账号
    isWeChatConnected: function () {
      return !!this.user.isWeChatConnected
    },

    // 平坦化的部门
    flattenedDepartments: function () {
      let flatArr = []

      // 递归平坦化每一级节点
      this.departmentsTree.forEach(flattenNode)

      function flattenNode (node) {
        flatArr.push(Object.assign({}, node, { children: undefined }))

        if (node.children instanceof Array) {
          node.children.forEach(flattenNode)
        }
      }

      return flatArr
    },

    // 适应 select tree 组件的逻辑缺陷，使其能正确地显示选中的部门
    selectedDepartment: function () {
      // 根据用户部门 ID 找出完整的部门对象
      for (let department of this.flattenedDepartments) {
        if (department.id === this.user.departmentId) {
          return department
        }
      }

      return {
        id: null,
        label: null,
        hash: null
      }
    }
  },
  watch: {
    // 传入新的 detail 时，重新组织其结构，并 clone 到 user
    detail: function () {
      this._cloneDetailToUser()
    }
  },
  created () {
    // 检查 props 的合法性
    // 任一非法则 throw，中断组件加载
    this._checkProps()

    // clone detail 到 user
    this._cloneDetailToUser()
  }
}
</script>

<style scoped lang="stylus">
  /deep/ .q-field--outlined.q-field--readonly .q-field__control:before {
    border-style solid
  }
  /deep/ .name {
    font-size 16px
  }
  .photo-box {
    margin-bottom 20px
    display flex
    flex-direction column
    height 292px
    justify-content space-between

    .photo {
      height 292px
      width 292px
      border 1px solid #D3D3D3
      border-radius 6px

      .upload-btn {
        height 100%
        width 100%

        &.dashed-border:after {
          $border-padding = 28px

          content ""
          display block
          position absolute
          top 0
          left 0
          height "calc(100% - %s)" % $border-padding
          width "calc(100% - %s)" % $border-padding
          margin ($border-padding / 2)
          border 1px dashed #FFF
        }
      }
    }
  }
</style>
